package org.acghub.mtdb.xmlgen.maker;

import org.acghub.mtdb.common.Bean;
import org.acghub.mtdb.common.Config;
import org.acghub.mtdb.common.Table;
import org.acghub.mtdb.common.exception.MtdbException;
import org.acghub.mtdb.util.StringUtil;
import org.acghub.mtdb.xmlgen.Maker;

import java.io.PrintStream;

/**
 * @author zhouhe
 */
public class TableMaker extends Maker<Table> {
    public TableMaker(Table inner, Config config) {
        super(inner, config);
    }

    @Override
    public void make() throws Exception {
        try (PrintStream ps = this.config().openTableFile(StringUtil.upperFirstChar(this.inner().getName()))) {
            this.make0(ps);
        }
    }

    private void make0(PrintStream ps) {
        String tableName = "_Tables_.INSTANCE." + this.inner().getName();
        String exception = MtdbException.class.getSimpleName();
        String className = StringUtil.upperFirstChar(this.inner().getName());
        String pair = org.acghub.mtdb.common.Pair.class.getSimpleName();

        String keyType = inner().getKeyType().javaInterfaceType();
        String valueType = inner().getValueType().javaInterfaceType();
        if (inner().getValueType() instanceof Bean) {
            valueType = config().beanFullPackage() + "." + valueType;
        }

        ps.println("package " + this.config().tableFullPackage() + ";");
        ps.println();
        ps.println("import org.acghub.mtdb.common.exception.MtdbException;");
        if (inner().getKeyType().supportAutoIncrement()) {
            ps.println("import org.acghub.mtdb.common.Pair;");
        }
        ps.println();
        ps.println("/**");
        ps.println("* xmlgen自动生成，不要修改此文件！！！");
        ps.println("*/");
        ps.println("public final class " + className + " {");

        // 1.autoIncrement
        if (inner().getKeyType().supportAutoIncrement()) {
            // minKey
            ps.printf(StringUtil.TAB + "public static %s minKey() throws %s {\n", keyType, exception);
            ps.println(StringUtil.tab(2) + "return " + tableName + ".minKey();");
            ps.println(StringUtil.TAB + "}");
            ps.println();

            // maxKey
            ps.printf(StringUtil.TAB + "public static %s maxKey() throws %s {\n", keyType, exception);
            ps.println(StringUtil.tab(2) + "return " + tableName + ".maxKey();");
            ps.println(StringUtil.TAB + "}");
            ps.println();

            // nextKey
            ps.printf(StringUtil.TAB + "public static %s nextKey() throws %s {\n", keyType, exception);
            ps.println(StringUtil.tab(2) + "return " + tableName + ".nextKey();");
            ps.println(StringUtil.TAB + "}");
            ps.println();

            // autoInsert
            ps.printf(StringUtil.TAB + "public static %s<%s, %s> insert() throws %s {\n", pair, keyType, valueType, exception);
            ps.println(StringUtil.tab(2) + "return " + tableName + ".insert();");
            ps.println(StringUtil.TAB + "}");
            ps.println();
        }

        // 2.exists(k)
        ps.printf(StringUtil.TAB + "public static boolean exists(%s k) throws %s {\n", keyType, exception);
        ps.println(StringUtil.tab(2) + "return " + tableName + ".exists(k);");
        ps.println(StringUtil.TAB + "}");
        ps.println();

        // 3.select(k)、 get(k)
        ps.printf(StringUtil.TAB + "public static %s select(%s k) throws %s {\n", valueType, keyType, exception);
        ps.println(StringUtil.tab(2) + "return " + tableName + ".select(k);");
        ps.println(StringUtil.TAB + "}");
        ps.println();

        ps.printf(StringUtil.TAB + "public static %s get(%s k) throws %s {\n", valueType, keyType, exception);
        ps.println(StringUtil.tab(2) + "return " + tableName + ".get(k);");
        ps.println(StringUtil.TAB + "}");
        ps.println();

        // 4.insert(k)
        if (inner().getValueType() instanceof Bean) {
            ps.printf(StringUtil.TAB + "public static %s insert(%s k) throws %s {\n", valueType, keyType, exception);
            ps.println(StringUtil.tab(2) + "return " + tableName + ".insert(k);");
            ps.println(StringUtil.TAB + "}");
            ps.println();
        }

        // 5.insert(k,v)
        ps.printf(StringUtil.TAB + "public static boolean insert(%s k, %s v) throws %s {\n", keyType, valueType, exception);
        ps.println(StringUtil.tab(2) + "return " + tableName + ".insert(k, v);");
        ps.println(StringUtil.TAB + "}");
        ps.println();

        // 8.delete(k)
        ps.printf(StringUtil.TAB + "public static void delete(%s k) throws %s {\n", keyType, exception);
        ps.println(StringUtil.tab(2) + tableName + ".delete(k);");
        ps.println(StringUtil.TAB + "}");
        ps.println();

        // 9.truncate()
        ps.printf(StringUtil.TAB + "public static void truncate() throws %s {\n", exception);
        ps.println(StringUtil.tab(2) + tableName + ".truncate();");
        ps.println(StringUtil.TAB + "}");
        ps.println();

        // 10.count()
        ps.printf(StringUtil.TAB + "public static long count() throws %s {\n", exception);
        ps.println(StringUtil.tab(2) + "return " + tableName + ".count();");
        ps.println(StringUtil.TAB + "}");
        ps.println();

        // 11. newValue
        ps.printf(StringUtil.TAB + "public static %s new%s() {\n", valueType, inner().getValueType().javaInterfaceType());
        ps.println(StringUtil.tab(2) + "return new "+ valueType + "();");
        ps.println(StringUtil.TAB + "}");
        ps.println();

        ps.println("}");

    }
}
